/***************************************************************************
 *   Copyright (C) 2006 by Robert R. Enderlein                             *
 *   robert_r_e@gmx.ch                                                     *
 *                                                                         *
 *   Modified and extended for Omega VII by Senary                         *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef OMEGA7_VECTOR_H
#define OMEGA7_VECTOR_H

#include <iostream>
#include <windows.h> //required by adll.h
#include <string>
#include "sdk_engine/adll.h"

class Angle;

/**
  @author Robert R. Enderlein <robert_r_e@gmx.ch>
 */
class Vector
{
	public:
		double x, y, z;

		///Set vector by carthesian coordinates
		Vector() : x(0.0), y(0.0), z(0.0) {}
		Vector(double x, double y, double z) : x(x), y(y), z(z) {}
		Vector(Vector const& rhs) : x(rhs.x), y(rhs.y), z(rhs.z) {}
		~Vector(){}

		// Creates a unit vector from an angle
		// equivalent to vec_for_angle() in GameStudio
		Vector(Angle const& rhs);

		/// Set a vector from it's GameStudio equivalent
		// Param rhs: the address of an VECTOR struct or, equivalently, the
		//            address of the x attribute, converted to VECTOR*
		Vector(VECTOR const* rhs);

		/// returns a random unit vector
		static Vector randomVector();

		///Set vector by cylindrical coordinates
		void cylindrical(double r, double phi, double h);

		///Set vector by spheric coordinates
		void spherical(double r, double theta, double phi);

		///Get the radius squared of the vector
		double r2() const;

		///Get the radius of the vector
		double r() const;

		///Get the phi angle (cylindrical & spheric)
		double phi() const;

		///Get the theta angle (spheric)
		double theta() const;


		///Assign operator
		Vector& operator=(Vector const& rhs);

		///Add to the current vector
		Vector& operator+=(Vector const& rhs);

		///Remove from the current vector
		Vector& operator-=(Vector const& rhs);

		///Multiply with a scalar
		Vector operator*(double const& k) const;

		///Multiply with a scalar
		Vector& operator*=(double const& k);

		///Divide by a scalar
		Vector operator/(double const& k) const;

		///Divide this vector by a scalar
		Vector& operator/=(double const& k);

		///Unary minus
		Vector operator-() const;

		///Projection
		Vector getProj(Vector const& rhs) const;
		
		///Project this vector on another one
		Vector& proj(Vector const& rhs);

		///Rotate this vector around "axis" by the amount "angle"
		Vector& rotate(Vector axis, double angle);

		///Rotate this vector towards "dest", by at most "angle".
		Vector& rotateTowards(Vector const& dest, double angle);


		/// Return a string representation of the vector
		std::string toString() const;

		// Converts a Vector back onto the supplied GameStudio VECTOR pointer
		// Param vec: the address of an VECTOR struct or, equivalently, the
		//            address of the x attribute, converted to VECTOR*
		void toGamestudio(VECTOR * vec) const;

};



///Normal addition
Vector operator+(Vector const& a, Vector const& b);

///Normal subtraction
Vector operator-(Vector const& a, Vector const& b);

///Multiply with a scalar
Vector operator*(double k, Vector const& rhs);

///Equals
bool operator==(Vector const& a, Vector const& b);

///Not equal
bool operator!=(Vector const& a, Vector const& b);

///Dot product
double dot(Vector const& a, Vector const& b);

///Cross product
Vector cross(Vector const& a, Vector const& b);

///Angle between two vectors
double angleBetween(Vector const& a, Vector const& b);


///Print a vector to  a stream
std::ostream& operator<<(std::ostream & os, Vector const& rhs);

#endif
